<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      function Vue({ data }) {
        this._data = data;

        //    数据代理
        for (let key in this._data) {
          Object.defineProperty(this, key, {
            get: function ProxyGetter() {
              return value;
            },
            set: function ProxySetter(val) {
              value = val;
            },
          });
        }
        observe(this._data);
      }

      function observe(value) {
        if (typeof value !== "object" || value === null) {
          return;
        }

        new Observer(value);
      }

      class Observer {
        constructor(value) {
          this.value = value;
        }

        //判断当前的值是否是一个数组,数组是不需要做数据劫持的,但是数组的内部如果是对象,则这个对象是要重新进行数据劫持的
        observeArray() {
          if (Array.isArray(this.value)) {
            this.value.forEach((item) => {
              observe(item);
            });
          }
        }

        // 当发布者接受的是一个对象的时候,进行数据劫持
        walk() {
          for (let key in this.value) {
            let value = this.value[key];
            defineReactive(this.value, key, value);
          }
        }
      }

      function defineReactive(obj, key, value) {
        observe(value);

        Object.defineProperty(obj, key, {
          get: function ReactiveGetter() {
            return value;
          },
          set: function ReactiveSetter(newVal) {
            value = newVal;
          },
        });
      }

      let vm = new Vue({
        data: {
          name: "pp",
          age: 22,
          friend: ["nancy", "judy", "lily"],
          score: {
            ch: 120,
            en: 110,
          },
        },
      });
    </script>
  </body>
</html>
